extern crate pkg_config;
use std::process::exit;
use std::env;
use std::ffi::CString;
use std::mem;

#[link(name = "cpp-cmake")]
extern {
    fn greet(s: *const std::os::raw::c_char, a: i32, b: i32);
}

//extern crate libc;
//use libc::c_int;
#[link(name = "emodp")]
extern {
fn em_get_size()-> i32;
}

use std::fs::File;
use std::io::{self, Read};

fn read_and_print_file(path: &str) -> io::Result<()> {
    let mut file = File::open(path)?;
    let mut contents = String::new();
    file.read_to_string(&mut contents)?;
    println!("File contents: {}", contents);
    Ok(())
}

extern crate message;
use message::{EmCoreMask, EmPoolCfg, EmConfT, rust_em_init};

fn main() {
    read_and_print_file("3rd/lib/pkgconfig/libemodp.pc").unwrap();

    let topdir = match env::current_dir() {
        Ok(path) => path,
        Err(_) => {
            eprintln!("Failed to get current directory.");
            exit(1);
        }
    };

    let pkg_config_path = format!("{}/3rd/lib/pkgconfig", topdir.display());
    env::set_var("PKG_CONFIG_PATH", &pkg_config_path);

    let lib_path = format!("{}/3rd/lib", topdir.display());
    match env::var("LD_LIBRARY_PATH") {
        Ok(mut ld_library_path) => {
            ld_library_path.push_str(":");
            ld_library_path.push_str(&lib_path);
            env::set_var("LD_LIBRARY_PATH", &ld_library_path);
        }
        Err(_) => {
            env::set_var("LD_LIBRARY_PATH", &lib_path);
        }
    }

    println!("top {} PKG_CONFIG_PATH: {} LIB: {}", topdir.display(),pkg_config_path,lib_path);

    let prompt = CString::new("Rust").unwrap();

    unsafe {
        greet(prompt.as_ptr(), 7, 11);
    }

    let mut em_conf = EmConfT {
        device_id: 0,   
        padding: [0; 6],          
        event_timer: 4,
        thread_per_core: 0,
        process_per_core: 1,
        core_count: 1,
        phys_mask: Default::default(),
        default_pool_cfg: Default::default(),
        log: Default::default(),
        input: Default::default(),
        output: Default::default(),
        api_hooks: Default::default(),
        idle_hooks: Default::default(), 
    };

    let test = mem::size_of::<EmCoreMask>();
    print!("Size of EmCoreMask in rust: {} bytes\n", test);

    let test = mem::size_of::<EmPoolCfg>();
    print!("Size of EmPoolCfg in rust: {} bytes\n", test);

    let result = unsafe { em_get_size() }; 
    let size = mem::size_of::<EmConfT>();
    if size != result as usize {
        println!("Size of em_conf_t in C: {} bytes", result);
        println!("Size of em_conf_t in rust: {} bytes", size);
        println!("Size of em_conf_t in C and rust are not equal.");
        exit(1);
    }
    
    let ret = rust_em_init(&mut em_conf);
    if ret == 0 {
        println!("main exit successful.");
    } else {
        println!("main exit failed. {}",ret);
    }
}